﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Burrow;
using System.ComponentModel;
using NHTools.Tools;
using System.Reflection;
using System.Collections;

namespace NHTools.Base
{
    [Serializable]
   public class NHEntityBase
    {
        static BurrowFramework _bf;
        public static BurrowFramework bf
        {
            get
            {
                if (_bf == null)
                    _bf = new BurrowFramework();
                return _bf;
            }
        }

        static ISession session;

        protected static ISession PersistenceSession
        {
            get
            {
                if (session == null || !session.IsOpen)
                    session = bf.GetSession();
                return session;
            }
        }

        #region Events
        public virtual event NHBaseEventHandler Deleting;

        protected virtual void OnDeleting(object entity)
        {
            OnDeleting(new NHEventArg(entity));
        }

        protected virtual void OnDeleting(NHEventArg e)
        {
            if (Deleting != null)
            {
                Deleting(this, e);
            }
        }

        public virtual event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (!this._ChangedProperites.Contains(e.PropertyName))
            {
                this._ChangedProperites.Add(e.PropertyName);
            }

            if (PropertyChanged != null)
            {
                PropertyChanged(this, e);
            }
        }

        #endregion

        public virtual int Id { get; set; }

        [System.Xml.Serialization.XmlIgnore()]
        public virtual DateTime CreatedDate { get; set; }

        [System.Xml.Serialization.XmlIgnore()]
        public virtual DateTime ModifiedDate { get; set; }

        public virtual object Tag { get; set; }

        public virtual bool IsNew { get { return Id == 0; } }

        public virtual int Delete()
        {
            if (this == null)
                return 0;
            ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                OnDeleting(this);
                PersistenceSession.Delete(this);
                PersistenceSession.Flush();
                trns.Commit();
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(this.GetType().Name, ex);
                trns.Rollback();
                throw ex;
            }
            return 1;
        }

        public virtual int Save()
        {
            if (this == null)
                return 0;

            if (this.Id == 0)
                CreatedDate = DateTime.Now;
            ModifiedDate = DateTime.Now;

            ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                PersistenceSession.Save(this);
                PersistenceSession.Flush();
                trns.Commit();
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(this.GetType().Name, ex);
                trns.Rollback();
                throw ex;
            }
            return 1;
        }

        public virtual int Update()
        {
            if (this == null)
                return 0;

            if (this.Id == 0)
                CreatedDate = DateTime.Now;
            ModifiedDate = DateTime.Now;

            ITransaction trns = PersistenceSession.BeginTransaction();
            try
            {
                PersistenceSession.Update(this);
                PersistenceSession.Flush();
                trns.Commit();
            }
            catch (Exception ex)
            {
                Provider.logger.ErrorException(this.GetType().Name, ex);
                trns.Rollback();
                throw ex;
            }
            return 1;
        }

        [System.Xml.Serialization.XmlIgnore()]
        public virtual Dictionary<string, string> CollectionRelations { get; set; }

        public virtual void CheckCollections()
        {
            if (CollectionRelations == null)
                return;

            foreach (var item in CollectionRelations)
            {
                PropertyInfo prp = this.GetType().GetProperty(item.Key);
                var clc = prp.GetValue(this, null);
                foreach (var itm in clc as IList)
                {
                    PropertyInfo chl = itm.GetType().GetProperty(item.Value);
                    if (chl.GetValue(itm, null) == null)
                        chl.SetValue(itm, this, null);
                }
            }
        }

        private List<string> _ChangedProperites = new List<string>();
        [System.Xml.Serialization.XmlIgnore()]
        public virtual List<string> ChangedProperties
        {
            get
            {
                return this._ChangedProperites;
            }
        }

        public virtual bool HasDataChanged()
        {
            return ChangedProperties.Count > 0 ? true : false;
        }
    }
}
